#include "ParticleSystem.hpp"
#include "our_math.h"
#include "our_time.h"


/** @brief update
  *
  * @todo: document this function
  */
void ParticleSystem::update()
{
    static float prev_time = get_seconds<float>();
    const float time = get_seconds<float>();

    if ( particles.size() > max_particles )
    {
        particles.erase(particles.begin(), particles.begin()+particles.size()-max_particles);
    }

    for(vector<ParticleEmitter*>::iterator it = emitters.begin(); it != emitters.end(); it++){
        (*it)->dt = (time-prev_time);
        (*it)->update();
    }

    for(vector<ParticleAttractor*>::iterator it = attractors.begin(); it != attractors.end(); it++){
        (*it)->update();
    }

    for(vector<Particle*>::iterator it = particles.begin(); it != particles.end(); it++){
        (*it)->y_acceleration += gravity_cos;
        (*it)->x_acceleration += gravity_sin;

        (*it)->dt = (time-prev_time);

        (*it)->update();
    }

    prev_time = time;
}

/** @brief ~ParticleSystem
  *
  * @todo: document this function
  */
 ParticleSystem::~ParticleSystem()
{

}

/** @brief ParticleSystem
  *
  * @todo: document this function
  */
 ParticleSystem::ParticleSystem():
 gravity(1), gravity_direction(180), max_particles(15000)
{
    set_gravity(gravity);
}

/** @brief output
  *
  * @todo: document this function
  */
void ParticleSystem::output()
{
    #define out(x) cout << #x << ": " << x << endl
    cout << "Particle count: " << particles.size() << endl;
    out(gravity);
    out(gravity_direction);
    #undef out
}

    /** @brief output_particles
  *
  * @todo: document this function
  */
void ParticleSystem::output_particles(unsigned int a, unsigned int b)
{
    for(unsigned int i = a; i < b && i < particles.size(); i++){
        particles[i]->output();
    }
}

/** @brief add_emitter
  *
  * @todo: document this function
  */
void ParticleSystem::add_emitter(ParticleEmitter *emitter)
{
    #ifdef DEBUG
    cout << "Adding emitter[" << emitters.size() << "]" << endl;
    #endif
    emitters.push_back(emitter);
}

void ParticleSystem::add_attractor(ParticleAttractor *attractor)
{
    attractors.push_back(attractor);
}

void ParticleSystem::set_gravity(float newgrav){
    gravity = newgrav;

    gravity_cos = cos(deg_to_rad(gravity_direction))*gravity;
    gravity_sin = sin(deg_to_rad(gravity_direction))*gravity;
}
